﻿using AutoWiring.Common;
using AutoWiring.Model;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using System.Text;

namespace AutoWiring.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class AutoWiringController : ControllerBase
    {
        private readonly CoreDBContext context;

        /// <summary>
        /// 依赖注入
        /// </summary>
        /// <param name="context"></param>
        public AutoWiringController(CoreDBContext context)
        {
            this.context = context;
        }

        /// <summary>
        /// 上传模型插件数据信息
        /// </summary>
        /// <param name="saveConfig"></param>
        /// <returns></returns>
        [HttpPost("UploadConfig")]
        public async Task<ActionResult<ResponseResult<string>>> UploadConfig(SaveConfig saveConfig)
        {
            try
            {
                // 判断数据库中是否有名称和CMD5加密值相同的数据

                ModelWiring mw = await context.modelwiring.Where(e =>
                        e.modelName == saveConfig.FileName && e.modelCode == comMethod.GetMD5Hash(saveConfig.FileName))
                    .FirstOrDefaultAsync();
                //  有数据并且禁止上传
                if (mw is { canUpload: "否" })
                {
                    // 只有存在数据并且禁止上传的时候才上传失败
                    return new ResponseResult<string>()
                    {
                        Code = HttpStatusCode.BadRequest,
                        Message = "当前数据已经存在并且禁止重复上传"
                    };
                }

                // 有数据可以上传时候则修改数据
                if (mw != null && mw.canUpload != "否")
                {
                    mw.modelName = saveConfig.FileName;
                    mw.modelCode = comMethod.GetMD5Hash(saveConfig.FileName);
                    mw.modelData = JsonConvert.SerializeObject(saveConfig);

                    context.Entry(mw).State = EntityState.Modified;

                    int r = await context.SaveChangesAsync();
                    if (r > 0)
                    {
                        return new ResponseResult<string>()
                        {
                            Code = HttpStatusCode.OK,
                            Message = "重复上传成功！"
                        };
                    }
                    else
                    {
                        return new ResponseResult<string>()
                        {
                            Code = HttpStatusCode.BadRequest,
                            Message = "重复上传失败！"
                        };
                    }
                }

                // 如果没有则添加数据
                if (mw == null)
                {
                    ModelWiring modelWiring = new ModelWiring
                    {
                        modelName = saveConfig.FileName,
                        modelCode = comMethod.GetMD5Hash(saveConfig.FileName),
                        modelData = JsonConvert.SerializeObject(saveConfig),
                        canUpload = "是"
                    };

                    context.Entry(modelWiring).State = EntityState.Added;

                    int r = await context.SaveChangesAsync();
                    if (r > 0)
                    {
                        return new ResponseResult<string>()
                        {
                            Code = HttpStatusCode.OK,
                            Message = "数据上传成功！",
                            Data = modelWiring.modelName
                        };
                    }
                    else
                    {
                        return new ResponseResult<string>()
                        {
                            Code = HttpStatusCode.BadRequest,
                            Message = "数据上传失败！"
                        };
                    }
                }

                return new ResponseResult<string>()
                {
                    Code = HttpStatusCode.BadRequest,
                    Message = "数据上传失败！"
                };
            }
            catch (Exception e)
            {
                return new ResponseResult<string>()
                {
                    Code = HttpStatusCode.BadRequest,
                    Message = "查询异常：" + e.Message
                };
            }
        }

        [HttpPost("GetData")]
        public async Task<ActionResult<ResponseResult<Dictionary<string, Dictionary<string, List<XYZ>>>>>> GetData(
            RequestPara requestPara)
        {
            try
            {
                // 判断数据库中是否有名称和CMD5加密值相同的数据
                ModelWiring mw = await context.modelwiring.Where(e =>
                        e.modelName == requestPara.FileName &&
                        e.modelCode == comMethod.GetMD5Hash(requestPara.FileName))
                    .FirstOrDefaultAsync();
                //  如果没有配置数据||数据为空||数据无法反序列化 则无发参与计算直接返回失败
                if (mw == null || string.IsNullOrEmpty(mw.modelData) ||
                    JsonConvert.DeserializeObject<SaveConfig>(mw.modelData) == null)
                {
                    return BadRequest(new ResponseResult<Dictionary<string, Dictionary<string, List<XYZ>>>>()
                    {
                        Code = HttpStatusCode.BadRequest,
                        Message = "当前请求清册数据不存在对应模型配置数据，请先上传模型配置数据",
                        Data = new Dictionary<string, Dictionary<string, List<XYZ>>>()
                    });
                }

                //一、 首先得到插件上传的配置信息，后续数据都在这里查询
                string jsonString = mw.modelData;

                #region 公共区域值

                // 解析最外层 JSON  
                JObject jsonObject = JObject.Parse(jsonString);

                // 解析 CommonConfig 部分(公共区域部分，没办法再封装了，下边每个都在用)
                var commonConfig = jsonObject["CommonConfig"];

                //主干道宽度
                string mainWidth = commonConfig["MainWidth"]?.ToString();
                //进线侧主干道宽度
                string JXmainWidth = commonConfig["JXMainWidth"]?.ToString();
                //馈线侧主干道宽度
                string KXmainWidth = commonConfig["KXMainWidth"]?.ToString();
                //电缆直径
                string diameter = commonConfig["Diameter"]?.ToString();
                //支架底层高度
                string csBottomHeight = commonConfig["CSBottomHeight"]?.ToString();
                //支架层距
                string csLayerSpace = commonConfig["CSLayerSpace"]?.ToString();
                //机柜支架底层高度
                string jsBottomHeight = commonConfig["JSBottomHeight"]?.ToString();
                //机柜支架层距
                string jsLayerSpace = commonConfig["JSLayerSpace"]?.ToString();

                // 计算机柜前的支架宽度
                List<CableContactItemSave> ccisList = JsonConvert.DeserializeObject<SaveConfig>(jsonString).ccisList;
                double width = comMethod.GetWidth(ccisList);

                #endregion

                //清册数据
                List<AutoConfig> ACList = requestPara.ACList;

                //每条计算线的数据
                List<CableContactItemExe> CCIEList = new List<CableContactItemExe>();
                //序号
                int index = -1;
                //对每组线的属性进行赋值
                foreach (AutoConfig ac in ACList)
                {
                    #region 每条线的属性赋值

                    CableContactItemExe ccie = new CableContactItemExe();
                    // 已知信息做复制处理

                    //序号
                    index++;
                    ccie.Id = index.ToString();

                    //电缆起点
                    ccie.cableStart = ac.cableStart;
                    //电缆终点
                    ccie.cableEnd = ac.cableEnd;
                    //电缆编号
                    ccie.cableNumber = ac.cableNumber;

                    //电缆名称 由电缆编号和电缆起点的最后一个字符构成
                    ccie.cableName = ac.cableNumber + ccie.cableStart[^1];
                    //是否走12层
                    ccie.isOneTwo = ac.isOneTwo;
                    //是否走顶层
                    ccie.isTop = ac.isTop;
                    //是否走对侧
                    ccie.IsOpposite = ac.IsOpposite;

                    //主干道宽度
                    ccie.mainWidth = comMethod.MainWidth(mainWidth);
                    ccie.JXmainWidth = comMethod.MainWidth(JXmainWidth);
                    ccie.KXmainWidth = comMethod.MainWidth(KXmainWidth);
                    // 线缆沟内的第一层支架高度 郭建增加了304.8
                    ccie.InLevelHeight = Convert.ToDouble(csBottomHeight) / 304.8;
                    // 线缆沟内的支架每层间隔 郭建增加了304.8
                    ccie.InHeight = Convert.ToDouble(csLayerSpace) / 304.8;
                    // 线缆沟外的第一层支架高度 郭建增加了304.8
                    ccie.supportFirstLevelHeight = Convert.ToDouble(jsBottomHeight) / 304.8;
                    // 线缆沟外的支架每层间隔 郭建增加了304.8
                    ccie.supportIntervalLevelHeight = Convert.ToDouble(jsLayerSpace) / 304.8;
                    // 支架宽度
                    ccie.supportWidth = width;
                    // 线缆半径（直径除以2再除以304.8）
                    ccie.cableRadius = Convert.ToDouble(diameter) / 2 / 304.8;

                    // 先把字段值都算出来

                    //TF线坐标点的集合的中心点
                    comMethod.BYQItemList(ccisList, ccie);

                    //预留槽坐标点的集合
                    var matchingItem = ccisList.Find(e => e.cableNumber == ccie.cableNumber);

                    if (matchingItem != null && !string.IsNullOrEmpty(matchingItem.YLCxyzList))
                    {
                        ccie.reservedSlotList =
                            JsonConvert.DeserializeObject<List<XYZ>>(matchingItem.YLCxyzList);
                        ccie.isJinXian = true;
                        //更改预留槽点的Z值高度
                        comMethod.YCLZValue(ccie);
                    }
                    else
                    {
                        ccie.isJinXian = false;
                    }

                    //电缆终点连接件坐标点的集合
                    comMethod.JGItemList(ccisList, ccie);

                    // 用的哪个支架
                    ccie.ZhiJiaList = JsonConvert.DeserializeObject<List<XYZ>>(comMethod
                        .GetZhiJia(ccisList, ccie.xyzEndList, ccie.xyzStartList, ccie).ZJxyzList);
                    //机柜前端两个支架的坐标
                    //第一个支架坐标 (支架前的边线起点)
                    ccie.firstSupport = ccie.ZhiJiaList[0];
                    //第二个支架坐标 (支架前的边线终点)
                    ccie.secondSupport = ccie.ZhiJiaList[1];

                    // 线缆沟末端中心点
                    ccie.finallyPoint = comMethod.CenterPoint(ccie.firstSupport, ccie.secondSupport);

                    #endregion

                    CCIEList.Add(ccie);
                }

                // 根据已经算好的值计算关键点，赋值到List<XYZ> resultPointList

                //新建一个字典，每个设备id为key，value为每个设备所有线的字典，每个线id为key，value为每个线所有关键点的集合
                Dictionary<string, Dictionary<string, List<XYZ>>> resultPointListDic =
                    new Dictionary<string, Dictionary<string, List<XYZ>>>();
                foreach (CableContactItemExe ccie in CCIEList)
                {
                    //变压器中心点
                    XYZ byqCenter = comMethod.CalculateCenterPoint(ccie.xyzStartList);

                    //机柜中心点
                    XYZ jgCenter = comMethod.CalculateCenterPoint(ccie.xyzEndList);

                    #region 预留槽数据

                    List<XYZ> SlotList = ccie.reservedSlotList;
                    //预留槽起点
                    XYZ startPoint = null;
                    //预留槽终点
                    XYZ endPoint = null;
                    //是否为进线侧，进线侧有预留槽数据
                    if (ccie.isJinXian)
                    {
                        //进线侧数据

                        //预留槽数据线排序
                        SlotList = SlotList.OrderBy(p => p.X).ToList();
                        // 只取预留槽的两个端点
                        List<XYZ> StartEndList =
                        [
                            SlotList.First(),
                            SlotList.Last()
                        ];
                        // 按距离排序，距离大的为起点，距离小的为终点
                        StartEndList = StartEndList.OrderBy(p => comMethod.CalculateDistance(p, jgCenter))
                            .ToList();
                        // 获取起点和终点
                        startPoint = StartEndList.Last(); // 距离最大的点为起点
                        endPoint = StartEndList.First(); // 距离最小的点为终点
                        if (SlotList.First() != startPoint)
                        {
                            SlotList.Reverse();
                        }
                        //重新按从起点到终点排序
                        //SlotList = SlotList.OrderBy(p => comMethod.CalculateDistance(p, startPoint)).ToList();
                    }

                    #endregion

                    //判断坐标轴的方向 yAxis为1表示正，越往下y越大；-1表示负，越往下y越小
                    int yAxis = jgCenter.Y - byqCenter.Y >= 0 ? 1 : -1;

                    //初始化
                    XYZ firstPoint;
                    XYZ firstLastPoint = new XYZ(0, 0, 0);
                    XYZ finallyPoint;
                    XYZ secondPoint;

                    List<XYZ> ylqyList = new List<XYZ>();

                    int xAxis;
                    if (ccie.isJinXian)
                    {
                        //进线侧

                        #region 1.第一个交点

                        XYZ firstPoint1;
                        List<XYZ> distancePoint =
                            comMethod.GetNearestPoints(byqCenter, JXmainWidth);
                        //第一个交点
                        if (yAxis > 0)
                        {
                            firstPoint1 = new XYZ(byqCenter.X, distancePoint[0].Y + ccie.cableRadius * 2 * 3,
                                ccie.InLevelHeight);
                            comMethod.UpdateYValues(SlotList, ccie.cableRadius * 2 * 4, yAxis);
                        }
                        else
                        {
                            firstPoint1 = new XYZ(byqCenter.X, distancePoint[0].Y - ccie.cableRadius * 2 * 3,
                                ccie.InLevelHeight);
                            comMethod.UpdateYValues(SlotList, ccie.cableRadius * 2 * 4, yAxis);
                        }

                        //第一个交点到预留槽起点的X值距离大于两倍的主线路宽度，则增加一个点，让点在对面多增加一个
                        if (Math.Abs((firstPoint1.X - startPoint.X)) > ccie.JXmainWidth * 3)
                        {
                            //新增一个交点，y值为第一个交点的y值，xz为预留槽起点值，并入到预留槽集合中
                            XYZ newPoint = new XYZ(byqCenter.X, startPoint.Y, ccie.InLevelHeight);
                            //并入到预留槽第一个点上
                            SlotList.Insert(0, newPoint);
                        }
                        else if ((firstPoint1.X > startPoint.X && firstPoint1.X < endPoint.X) ||
                                 (firstPoint1.X < startPoint.X && firstPoint1.X > endPoint.X)
                                )
                        {
                            //如果不是很宽，并且第一个交点的X值在预留槽的两个端点的X值范围内，则取离交点距离最近的点，为预留槽的起点，去掉预留槽起点之前的点
                            double distanceMin = Double.MaxValue;
                            double distance = 0.00;
                            XYZ closePoint = new XYZ(0, 0, 0);
                            int closestIndex = -1; // 用于记录最近点的索引
                            int currentIndex = 0; // 用于遍历 SlotList 的索引

                            for (int i = 0; i < (SlotList.Count / 2) - 1; i++)
                            {
                                distance = firstPoint1.DistanceTo(SlotList[i]);

                                if (distance < distanceMin)
                                {
                                    closePoint = SlotList[i];
                                    distanceMin = distance;
                                    closestIndex = currentIndex; // 更新最近点的索引
                                }

                                currentIndex++; // 索引递增
                            }

                            //删除从起点到该点的所有点
                            if (closestIndex >= SlotList.Count / 2)
                            {
                                closestIndex = SlotList.Count / 2 - 1;
                                SlotList.RemoveRange(0, closestIndex);
                            }
                            else
                            {
                                SlotList.RemoveRange(0, closestIndex);
                            }
                        }

                        #endregion

                        #region 预留槽终点是否跳到对侧

                        XYZ Point;
                        //是否需要跳到对侧
                        if (ccie.IsOpposite)
                        {
                            //第二个交点的y值加上主干道宽度
                            Point = yAxis > 0
                                ? new XYZ(endPoint.X, endPoint.Y - ccie.JXmainWidth + ccie.cableRadius * 2 * 6,
                                    endPoint.Z)
                                : new XYZ(endPoint.X, endPoint.Y + ccie.JXmainWidth - ccie.cableRadius * 2 * 6,
                                    endPoint.Z);
                            //并入到预留槽最后个点上
                            SlotList.Add(Point);
                        }

                        #endregion

                        #region 2.第二个交点

                        //预留槽终点的y轴坐标 与 线缆沟末端中心点的x轴坐标
                        //线缆沟末端中心点
                        XYZ finallyPoint1 = ccie.finallyPoint;

                        //第二个交点
                        XYZ secondPoint1 = new XYZ(finallyPoint1.X, SlotList[^1].Y, SlotList[^1].Z);

                        // 机柜中心点在线缆沟末端中心点哪侧就往哪侧偏移

                        // 计算机柜中心点与目标点（如线缆沟末端）的相对位置
                        xAxis = jgCenter.X - finallyPoint1.X >= 0 ? 1 : -1;
                        ccie.xAxis = xAxis;

                        // 根据 xAxis 判断机柜中心点相对位置，设置 isLeft 属性
                        ccie.isLeft = xAxis == -1; // xAxis为-1表示左侧，设置为 true

                        //线缆沟出侧方向的边线宽度
                        double edgeWidth = Math.Round(Math.Abs(ccie.firstSupport.X - ccie.secondSupport.X), 4);

                        // 判断是左偏移还是右偏移，并更新 X 坐标
                        double x;
                        if (xAxis > 0) // 偏右，X 越大
                        {
                            x = secondPoint1.X + edgeWidth / 2 - 6 * ccie.cableRadius;
                        }
                        else // 偏左，X 越小
                        {
                            x = secondPoint1.X - edgeWidth / 2 + 6 * ccie.cableRadius;
                        }

                        //第二个交点最终值以及线缆沟末端点
                        secondPoint1 = new XYZ(x, SlotList[^1].Y, SlotList[^1].Z);
                        finallyPoint1 = new XYZ(x, finallyPoint1.Y, SlotList[^1].Z);

                        #endregion

                        firstPoint = firstPoint1;
                        finallyPoint = finallyPoint1;
                        secondPoint = secondPoint1;
                    }
                    else
                    {
                        //馈线侧

                        //起点设备的中心点
                        XYZ FeederLineCenter = byqCenter;

                        List<XYZ> distancePoint =
                            comMethod.GetNearestPoints(byqCenter, KXmainWidth); //?这两个点要重新再取值

                        #region 第一个交点

                        XYZ firstPoint1;
                        //是否跳到对面
                        //如果跳到对侧，远离起点的道路宽度的坐标点  用远点
                        if (ccie.IsOpposite)
                        {
                            //如果是跳到对面需要增加一个点
                            firstPoint1 = new XYZ(
                                FeederLineCenter.X,
                                distancePoint[1].Y -
                                (yAxis > 0 ? ccie.cableRadius * 2 * 4 : -ccie.cableRadius * 2 * 4),
                                ccie.InLevelHeight
                            );
                            firstLastPoint = new XYZ(
                                FeederLineCenter.X,
                                distancePoint[0].Y +
                                (yAxis > 0 ? ccie.cableRadius * 2 * 4 : -ccie.cableRadius * 2 * 4),
                                ccie.InLevelHeight
                            );
                        }
                        else
                        {
                            firstPoint1 = new XYZ(
                                FeederLineCenter.X,
                                distancePoint[0].Y +
                                (yAxis > 0 ? ccie.cableRadius * 2 * 4 : -ccie.cableRadius * 2 * 4),
                                ccie.InLevelHeight
                            );
                        }

                        #endregion


                        #region 第二个交点

                        //第一个交点的y轴坐标 与 线缆沟末端中心点的x轴坐标
                        //线缆沟末端中心点
                        XYZ finallyPoint1 = ccie.finallyPoint;

                        //第二个交点
                        XYZ secondPoint1 = new XYZ(finallyPoint1.X, firstPoint1.Y, firstPoint1.Z);

                        // 机柜中心点在线缆沟末端中心点哪侧就往哪侧偏移

                        // 计算机柜中心点与目标点（如线缆沟末端）的相对位置
                        xAxis = jgCenter.X - finallyPoint1.X >= 0 ? 1 : -1;
                        ccie.xAxis = xAxis;

                        // 根据 xAxis 判断机柜中心点相对位置，设置 isLeft 属性
                        ccie.isLeft = xAxis == -1; // xAxis为-1表示左侧，设置为 true

                        //线缆沟出侧方向的边线宽度
                        double edgeWidth = Math.Round(Math.Abs(ccie.firstSupport.X - ccie.secondSupport.X), 4);

                        // 判断是左偏移还是右偏移，并更新 X 坐标
                        double x;
                        if (xAxis > 0) // 偏右，X 越大
                        {
                            x = secondPoint1.X + edgeWidth / 2 - 6 * ccie.cableRadius;
                        }
                        else // 偏左，X 越小
                        {
                            x = secondPoint1.X - edgeWidth / 2 + 6 * ccie.cableRadius;
                        }

                        //第二个交点最终值以及线缆沟末端点
                        secondPoint1 = new XYZ(x, firstPoint1.Y, firstPoint1.Z);
                        finallyPoint1 = new XYZ(x, finallyPoint1.Y, firstPoint1.Z);

                        // 如果机柜在起点右侧，则T线上移，F线下移
                        // 如果机柜在起点左侧侧，则F线上移，T线下移
// 支架组的中心点
                        XYZ ZJCenterPoint = comMethod.KXJGLoaction(ccie);

                        //判断机柜和起点的坐标
                        int startAndEnd = ZJCenterPoint.X - byqCenter.X >= 0 ? 1 : -1; //如果为1机柜在右侧，如果为-1机柜在左侧

                        if (startAndEnd > 0)
                        {
                            //机柜在右侧 
                            // 如果是T线Y值上移一部分距离
                            if (ccie.xyzStartDic.Keys.Any(key => key.StartsWith("T")))
                            {
                                firstPoint1 = new XYZ(firstPoint1.X, firstPoint1.Y + ccie.cableRadius * 2 * 2,
                                    firstPoint1.Z);
                                secondPoint1 = new XYZ(secondPoint1.X,
                                    secondPoint1.Y + ccie.cableRadius * 2 * 2,
                                    secondPoint1.Z);
                            }

                            if (ccie.xyzStartDic.Keys.Any(key => key.StartsWith("F")))
                            {
                                firstPoint1 = new XYZ(firstPoint1.X, firstPoint1.Y - ccie.cableRadius * 2 * 2,
                                    firstPoint1.Z);
                                secondPoint1 = new XYZ(secondPoint1.X,
                                    secondPoint1.Y - ccie.cableRadius * 2 * 2,
                                    secondPoint1.Z);
                            }
                        }
                        else
                        {
                            // 如果是T线Y值上移一部分距离
                            if (ccie.xyzStartDic.Keys.Any(key => key.StartsWith("F")))
                            {
                                firstPoint1 = new XYZ(firstPoint1.X, firstPoint1.Y + ccie.cableRadius * 2 * 2,
                                    firstPoint1.Z);
                                secondPoint1 = new XYZ(secondPoint1.X,
                                    secondPoint1.Y + ccie.cableRadius * 2 * 2,
                                    secondPoint1.Z);
                            }

                            if (ccie.xyzStartDic.Keys.Any(key => key.StartsWith("T")))
                            {
                                firstPoint1 = new XYZ(firstPoint1.X, firstPoint1.Y - ccie.cableRadius * 2 * 2,
                                    firstPoint1.Z);
                                secondPoint1 = new XYZ(secondPoint1.X,
                                    secondPoint1.Y - ccie.cableRadius * 2 * 2,
                                    secondPoint1.Z);
                            }
                        }

                        // if (ccie.xyzStartDic.Keys.Any(key => key.StartsWith("T")))
                        // {
                        //     firstPoint1 = new XYZ(firstPoint1.X, firstPoint1.Y + ccie.cableRadius * 2 * 2,
                        //         firstPoint1.Z);
                        //     secondPoint1 = new XYZ(secondPoint1.X,
                        //         secondPoint1.Y + ccie.cableRadius * 2 * 3,
                        //         secondPoint1.Z);
                        // }
                        //
                        // if (ccie.xyzStartDic.Keys.Any(key => key.StartsWith("F")))
                        // {
                        //     firstPoint1 = new XYZ(firstPoint1.X, firstPoint1.Y - ccie.cableRadius * 2 * 2,
                        //         firstPoint1.Z);
                        //     secondPoint1 = new XYZ(secondPoint1.X,
                        //         secondPoint1.Y - ccie.cableRadius * 2 * 3,
                        //         secondPoint1.Z);
                        // }

                        #endregion

                        firstPoint = firstPoint1;
                        finallyPoint = finallyPoint1;
                        secondPoint = secondPoint1;


                        // 支架组的中心点相对电缆起点中心点的位置

                        bool isLeft = comMethod.ZJAndStart(ZJCenterPoint, ccie.startPointCenter);

                        if (isLeft)
                        {
                            // 如果是起点在支架点的左侧
                            // 出来的线都往右侧
                            // 往右侧走线的，在右侧的半径大，在左侧的半径小
                            // 如果是看TF线呢，目前来说是不是更快一点
                            // 后期还是得换成线
                            // 找起点线的x与起点中心点作比较，决定是左侧还是右侧
                            if (ccie.IsOpposite)
                            {
                                ylqyList = comMethod.KXLineAdjustedYLPoint(firstPoint1, ccie);
                            }
                            else
                            {
                                ylqyList = comMethod.KXLineYLPoint(firstPoint1, ccie, ZJCenterPoint);
                            }
                        }
                        else
                        {
                            // 如果是起点在支架点的右侧
                            // 出来的线都往左侧
                            // 往左侧走线的，在左侧的半径大，在右侧的半径小
                            if (ccie.IsOpposite)
                            {
                                ylqyList = comMethod.KXRightLineAdjustedYLPoint(firstPoint1, ccie);
                            }
                            else
                            {
                                ylqyList = comMethod.KXLineRightYLPoint(firstPoint1, ccie, ZJCenterPoint);
                            }
                        }
                    }

                    #region 连支架点

                    //偏移量
                    double moveValue =
                        Math.Round((ccie.supportWidth / 2 - ccie.cableRadius * 4) / 3 + ccie.cableRadius, 4);
                    ccie.moveValue = moveValue;

                    //根据xAxis值判断是偏左还是偏右
                    //偏右，支架点的X值加上偏移量；偏左，支架点的X值减去偏移量；
                    XYZ ZJPoint1 = ccie.ZhiJiaList[^2]; //倒数第二个点
                    XYZ ZJPoint2 = ccie.ZhiJiaList[^1]; //倒数第一个点

                    XYZ ZJStartPoint = null;
                    XYZ ZJEndPoint = null;

                    if (ZJPoint1.X == ZJPoint2.X && ZJPoint1.Y == ZJPoint2.Y && ZJPoint1.Z == ZJPoint2.Z)
                    {
                        //两个支架点指的同一个支架，走一个就行
                        ccie.isSameZhiJia = true;
                        //偏移后的两个点
                        ZJStartPoint = xAxis > 0
                            ? new XYZ(ZJPoint1.X + moveValue, ZJPoint1.Y, ZJPoint1.Z)
                            : new XYZ(ZJPoint1.X - moveValue, ZJPoint1.Y, ZJPoint1.Z);
                    }
                    else
                    {
                        //不一样
                        ccie.isSameZhiJia = false;
                        //偏移后的两个点
                        ZJStartPoint = xAxis > 0
                            ? new XYZ(ZJPoint1.X + moveValue, ZJPoint1.Y, ZJPoint1.Z)
                            : new XYZ(ZJPoint1.X - moveValue, ZJPoint1.Y, ZJPoint1.Z);
                        ZJEndPoint = xAxis > 0
                            ? new XYZ(ZJPoint2.X + moveValue, ZJPoint2.Y, ZJPoint2.Z)
                            : new XYZ(ZJPoint2.X - moveValue, ZJPoint2.Y, ZJPoint2.Z);
                    }

                    #endregion

                    #region 添加点到最终返回的集合中resultPointList

                    //变压器点
                    ccie.resultPointList.Add(byqCenter);
                    if (firstLastPoint.X != 0 && firstLastPoint.Y != 0 && firstLastPoint.Z != 0)
                    {
                        ccie.resultPointList.Add(firstLastPoint);
                    }


                    //第一个交点
                    ccie.resultPointList.Add(firstPoint);

                    //根据是否是进线侧判用哪个预留槽
                    if (ccie.isJinXian)
                    {
                        //预留槽集合点
                        ccie.resultPointList.AddRange(SlotList);
                    }
                    else
                    {
                        ccie.resultPointList.AddRange(ylqyList);
                    }

                    //第二个交点
                    ccie.resultPointList.Add(secondPoint);
                    //线缆沟末端点
                    ccie.resultPointList.Add(finallyPoint);
                    //机柜前的支架点
                    if (ZJPoint1.X == ZJPoint2.X && ZJPoint1.Y == ZJPoint2.Y && ZJPoint1.Z == ZJPoint2.Z)
                    {
                        ccie.resultPointList.Add(new XYZ(ZJStartPoint.X, ZJStartPoint.Y,
                            ccie.supportFirstLevelHeight));
                    }
                    else
                    {
                        ccie.resultPointList.Add(new XYZ(ZJStartPoint.X, ZJStartPoint.Y,
                            ccie.supportFirstLevelHeight));
                        ccie.resultPointList.Add(new XYZ(ZJEndPoint.X, ZJEndPoint.Y,
                            ccie.supportFirstLevelHeight));
                    }

                    //机柜中心点
                    ccie.resultPointList.Add(jgCenter);

                    #endregion


                    #region 线路偏移 没有加到最终返回的集合中

                    if (ccie.isJinXian)
                    {
                        var (leftOffsetPoints, rightOffsetPoints, mainOffsetPoints) = comMethod.OffsetPolyline(
                            ccie,
                            ccie.resultPointList, ccie.cableRadius * 3, ccie.InHeight,
                            ccie.supportIntervalLevelHeight,
                            ccie.supportFirstLevelHeight, ccie.isOneTwo);

                        ccie.resultPointList = mainOffsetPoints;

                        //将偏移后的点集合添加到字典中
                        ccie.resultPointDic.Add("1", leftOffsetPoints); //第一层线左侧
                        ccie.resultPointDic.Add("2", ccie.resultPointList); //第一层线中间
                        ccie.resultPointDic.Add("3", rightOffsetPoints); //第一层线右侧
                    }
                    else
                    {
                        var (mainPoint, upOnePoints, upTwoPoints) = comMethod.PolylineUpDown(ccie);

                        ccie.resultPointDic.Add("1", mainPoint); //第一层
                        ccie.resultPointDic.Add("2", upOnePoints); //上一层
                        ccie.resultPointDic.Add("3", upTwoPoints); //上两层
                    }

                    #endregion

                    #region 起点终点对应连接的点

                    //获取到一个设备中所有线对应的起点和终点
                    Dictionary<string, List<XYZ>> StartEndPoint =
                        comMethod.StartEndSamePoint(ccie.xyzStartDic, ccie.xyzEndDic);

                    //处理起点

                    comMethod.ProcessSortedLine(ccie, StartEndPoint);

                    //终点连接机柜的点处理
                    if (ccie.isJinXian)
                    {
                        comMethod.EndProcessing(ccie);
                    }
                    else
                    {
                        comMethod.VerticalEndProcessing(ccie);
                    }

                    #endregion

                    //郭建修改了曲线的生成代码
                    #region 处理数据曲线 
                    //
                    // foreach (var kvp in ccie.resultPointDic)
                    // {
                    //     
                    //     double propertyScale = 0.4;
                    //     double r = ccie.cableRadius * 2 * 10;
                    //     // 获取当前键和对应的点列表
                    //     string key = kvp.Key;
                    //     List<XYZ> points = kvp.Value;
                    //     List<XYZ> tempPoints = new List<XYZ>();
                    //     foreach (var p in points) tempPoints.Add(new XYZ(p.X, p.Y, p.Z));
                    //     points = tempPoints;
                    //
                    //     List<XYZ> resutNew = new List<XYZ>();
                    //     resutNew.Add(points[0]);
                    //     List<XYZ> desList = comMethod.exDistinctElement(points);
                    //     for (int i = 1; i < desList.Count - 1; i += 1)
                    //     {
                    //         XYZ p0 = resutNew[resutNew.Count - 1];
                    //         XYZ p1 = desList[i];
                    //         XYZ p2 = desList[i + 1];
                    //         double dis1 = p0.DistanceTo(p1);
                    //         double dis2 = p2.DistanceTo(p1);
                    //         XYZ v1 = p0.Subtract(p1).Normalize();
                    //         XYZ v2 = p2.Subtract(p1).Normalize();
                    //
                    //         if (dis1 * 0.5 > r)
                    //             p0 = p1.Add(v1.Multiply(r));
                    //         else
                    //             p0 = p1.Add(v1.Multiply(dis1 * propertyScale));
                    //         if (dis2 * 0.5 > r)
                    //             p2 = p1.Add(v2.Multiply(r));
                    //         else
                    //             p2 = p1.Add(v2.Multiply(dis2 * propertyScale));
                    //
                    //         List<XYZ> resultPoints = comMethod.generalArc(p0, p1, p2);
                    //         resutNew = resutNew.Concat(resultPoints).ToList();
                    //     }
                    //     resutNew.Add(desList[desList.Count - 1]);
                    //     points = resutNew;
                    //
                    //     ccie.resultPointDic[key] = points;
                    // }
                    #endregion


                    resultPointListDic.Add(ccie.cableName, ccie.resultPointDic);
                }


                #region 最终结果文件格式输出

                // 定义输出文件路径
                string outputPath = @"E:\resultPointListDicOutput.txt";

                try
                {
                    #region 按格式输出

                    //using (StreamWriter writer = new StreamWriter(outputPath))
                    //{
                    //    // 遍历外层字典
                    //    foreach (var outerPair in resultPointListDic)
                    //    {
                    //        writer.WriteLine($"Outer Key: {outerPair.Key}");
                    //        writer.WriteLine(new string('-', 50)); // 分隔线

                    //        // 遍历内层字典
                    //        foreach (var innerPair in outerPair.Value)
                    //        {
                    //            writer.WriteLine($"\tInner Key: {innerPair.Key}");
                    //            writer.WriteLine("\tValues:");

                    //            // 遍历 List<XYZ>，输出每个 XYZ 对象的值
                    //            foreach (var xyz in innerPair.Value)
                    //            {
                    //                writer.WriteLine($"\t\tXYZ: ({xyz.X}, {xyz.Y}, {xyz.Z})");
                    //            }
                    //            writer.WriteLine(); // 内层字典结束后空行
                    //        }
                    //        writer.WriteLine(); // 外层字典结束后空行
                    //    }
                    //}

                    //Console.WriteLine("结果已成功输出到文件: " + outputPath);

                    #endregion

                    // 将字典序列化为 JSON 字符串
                    string resultString = JsonConvert.SerializeObject(resultPointListDic);
                    // 按字符串输出
                    await using (StreamWriter writer = new StreamWriter(outputPath, false, Encoding.UTF8))
                    {
                        await writer.WriteAsync(resultString); // 写入字符串
                    }

                    Console.WriteLine("结果已成功输出到文件: " + outputPath);
                }

                #endregion

                catch (Exception ex)
                {
                    Console.WriteLine("发生错误: " + ex.Message);
                }

                // 返回成功结果
                // 返回 OK 响应，将嵌套字典组合并返回
                return new ResponseResult<Dictionary<string, Dictionary<string, List<XYZ>>>>()
                {
                    Code = HttpStatusCode.OK,
                    Data = resultPointListDic, // 直接返回已有的数据字典
                    Message = "操作成功"
                };
            }
            catch (Exception e)
            {
                return StatusCode(500, new ResponseResult<Dictionary<string, List<XYZ>>>()
                {
                    Code = HttpStatusCode.InternalServerError,
                    Message = "查询异常：" + e.Message
                });
            }

            return null;
        }
    }
}